// call方法，可以指定该函数内部this的指向（即函数执行时所在的作用域），然后在所指定的作用域中，调用该函数。并且会立即执行该函数。

// Step1: 把第二个到最后一个参数作为函数执行时要传入的参数
// Step2: 把函数执行时的this指向第一个参数
// Step3: 在上面这个特殊的上下文中执行函数

// foo()-- -> foo.call(window)
// obj.foo()-- > obj.foo.call(obj)

var keith = {
	rascal: 123,
}

var rascal = 456

function a(a, b) {
	console.log(this.rascal)
	if (a && b) {
		console.log(a + b)
	}
}

a() //456  // TODO: 如果是严格模式，此处内部 this 为 undefined
a.call() //456
a.call(null) //456
a.call(undefined) //456
a.call(this) //456
a.call(keith, 1, 3) //123 4

a.apply(keith, [1, 3]) //123 4


// 如果使用call方法将this关键字指向keith对象，也就是将该函数执行时所在的作用域为keith对象，返回结果为123。

// call()方法可以传递多个参数。第一个参数是指定函数内部中this的指向（也就是函数执行时所在的作用域），第二个参数以后是函数调用时需要传递的参数。

// 第一个参数可以是null，undefined，this,其他对象。设置为null，undefined，this,或者空 表明函数keith此时处于全局作用域。

/* apply  可以找出数组中最大数 */
// Javascript中是没有提供找出数组中最大值的方法的，结合使用继承自Function.prototype的apply和Math.max方法，就可以返回数组的最大值。
var arr = [1, 213, 5435, 111111]
console.log(Math.max.apply(null, arr))

/* bind 方法用于指定函数内部的this指向（执行时所在的作用域），然后返回一个新函数。bind方法并非立即执行一个函数。 */
/* bind() 函数会创建一个新函数（称为绑定函数），新函数与被调函数（绑定函数的目标函数）具有相同的函数体,可以实现偏函数，有点柯里化的感觉

柯里化是将一个多参数函数转换成多个单参数函数，也就是将一个 n 元函数转换成 n 个一元函数。
偏函数则是固定一个函数的一个或者多个参数，也就是将一个 n 元函数转换成一个 n - x 元函数。

	function add(a, b,c) {
		return a + b + c;
	}
	var fn = add.bind(null,1,2);
	console.log(fn(3)); //结果3
*/
var keith = {
	a: 1,
	count: function () {
		console.log(this.a++)
	},
}

var obj = {
	a: 100,
}
var f = keith.count.bind(obj)
f() //100
f() //101
f() //102
// 我们也可以给bind方法传递参数，第一个参数如果为null或者undefined或者this，会将函数内部的this对象指向全局环境；第二个为调用时需要的参数，并且传递参数的形式与call方法相同。

function keith(a, b) {
	return a + b
}
console.log(keith.apply(null, [1, 4])) //5
console.log(keith.call(null, 1, 4)) //5
console.log(keith.bind(null, 1, 4)) //keith()
console.log(keith.bind(null, 1, 4)()) //5
// 上面代码中，可以看出call，apply，bind三者的区别：call和apply方法都是在调用之后立即执行的。而bind调用之后是返回原函数，需要再调用一次才行，
